/**
 * \file
 *
 * Mount a KFS filesystem using FUSE: Filesystem in Userspace
 */
#include "precompiled.hpp"
#include "kfs.hpp"
#include "kfs_impl.hpp"
#include "kfs_fuse.hpp"
//#include <boost/program_options/config.hpp>
//#include <boost/program_options/environment_iterator.hpp>
//#include <boost/program_options/eof_iterator.hpp>
#include <boost/program_options/errors.hpp>
#include <boost/program_options/option.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/positional_options.hpp>
//#include <boost/program_options/value_semantic.hpp>
#include <boost/program_options/variables_map.hpp>
//#include <boost/program_options/version.hpp>
#include <fuse.h>
#include <cstdio>
#include <cstring>
#include <errno.h>
#include <fcntl.h>
#include <iostream>

using boost::scoped_array;
using std::cerr;  using std::cin;  using std::cout;  using std::endl;
using std::string;  using std::vector;

namespace po = boost::program_options;


int main(int argc, char *argv[])
{
    // Declare the supported options.
    po::options_description desc("Mounting options");
    desc.add_options()
        ("device", po::value<string>()->required(), "The device on which the "
            " filesystem will be created")
        ("help", "Produce this help message")
    ;
    //po::positional_options_description pd;
    //pd.add("device", 1);

    try
    {
        po::parsed_options parsed = po::command_line_parser(argc, argv)
        .options(desc)/*.positional(pd)*/.allow_unregistered().run();

        po::variables_map vm;
        po::store(parsed, vm);
        // Check for a "help" request before we enforce mandatory options.
        if (vm.count("help"))
        {
            cout << desc;
            return 0;
        }
        po::notify(vm);

        vector<string> fuseOptions = po::collect_unrecognized(parsed.options,
            po::include_positional);
        fuseOptions.insert(fuseOptions.begin(), argv[0]);
        scoped_array<char*> fuse_argv( new char*[fuseOptions.size()] );
        for(size_t i = 0; i < fuseOptions.size(); ++i)
        {
            size_t const n = fuseOptions[i].size();
            fuse_argv[i] = new char[n + 1];
            if(n != 0)
                memcpy(fuse_argv[i], &fuseOptions[i][0], n);
            fuse_argv[i][n] = '\0';
        }
        int r = fuse_main(fuseOptions.size(), fuse_argv.get(),
            kfsys_fuse_ops(), &vm /* user data*/);
        for(size_t i = 0; i < fuseOptions.size(); ++i)
        {
            delete[] fuse_argv[i];
        }
        return r;
   }
    catch(std::exception& e)
    {
        fprintf(stderr, "%s: Unexpected exception: %s\n", __FUNCTION__,
            e.what());
        return 1;
    }
}
